package pl.edu.agh.lab2.sr.beans;

import java.io.Serializable;

public class GameMap implements Serializable {

	private static final long serialVersionUID = -582424194340474623L;
	private static final int DIMENSION = 10;

	public static int getDimension() {
		return DIMENSION;
	}

	private MyFieldStates myMap[][];
	private OpponentFieldStates opponentMap[][];

	public GameMap() {
		this.myMap = initMyMap();
		this.opponentMap = initOpponentMap();
	}

	public MyFieldStates[][] getMyMap() {
		return myMap;
	}

	public OpponentFieldStates[][] getOppositeMap() {
		return opponentMap;
	}

	public MyFieldStates getMyCell(Field field) {
		return myMap[field.getNormalizedX()][field.getNormalizedY()];
	}

	public OpponentFieldStates getOpponentCell(Field field) {
		return opponentMap[field.getNormalizedX()][field.getNormalizedY()];
	}

	public void setMyCell(Field field, MyFieldStates state) {
		myMap[field.getNormalizedX()][field.getNormalizedY()] = state;
	}

	public void setOpponentCell(Field field, OpponentFieldStates state) {
		opponentMap[field.getNormalizedX()][field.getNormalizedY()] = state;
	}

	public void initMyMapWithSampleShips(int i) {

		myMap[i % DIMENSION][0] = MyFieldStates.Ship;
		myMap[DIMENSION - 1][i % DIMENSION] = MyFieldStates.Ship;
		myMap[0][DIMENSION - 1] = MyFieldStates.Ship;
		myMap[DIMENSION - 1][DIMENSION - 1] = MyFieldStates.Ship;
		myMap[DIMENSION - 1][(3 +i) % DIMENSION] = MyFieldStates.Ship;

	}

	public void initMyMapWithSampleData() {
		myMap[0][0] = MyFieldStates.Ship;
		myMap[DIMENSION - 1][0] = MyFieldStates.Ship;
		myMap[0][DIMENSION - 1] = MyFieldStates.Ship;
		myMap[DIMENSION - 1][DIMENSION - 1] = MyFieldStates.Ship;
		myMap[DIMENSION - 1][4] = MyFieldStates.Ship;

		myMap[2][2] = MyFieldStates.HittedShip;
		myMap[4][4] = MyFieldStates.HittedShip;

		myMap[6][5] = MyFieldStates.MissedShot;
		myMap[5][7] = MyFieldStates.MissedShot;
		myMap[2][3] = MyFieldStates.MissedShot;
	}

	public void initOpponentMapWithSampleData() {
		opponentMap[0][0] = OpponentFieldStates.MissedShot;
		opponentMap[0][DIMENSION - 1] = OpponentFieldStates.MissedShot;
		opponentMap[DIMENSION - 1][0] = OpponentFieldStates.MissedShot;
		opponentMap[DIMENSION - 1][DIMENSION - 1] = OpponentFieldStates.MissedShot;
		opponentMap[3][5] = OpponentFieldStates.MissedShot;

		opponentMap[2][3] = OpponentFieldStates.HittedShip;
		opponentMap[6][1] = OpponentFieldStates.HittedShip;
		opponentMap[4][6] = OpponentFieldStates.HittedShip;
		opponentMap[1][3] = OpponentFieldStates.HittedShip;

	}

	public String getLegend() {
		StringBuilder sb = new StringBuilder();

		sb.append("My: ");
		for (MyFieldStates status : MyFieldStates.values()) {
			if (status == MyFieldStates.Empty) {
				continue;
			}
			sb.append(status.toString());
			sb.append(" - ");
			sb.append(status.name());
			sb.append("; ");
		}
		sb.append("\n");

		sb.append("Opponent: ");
		for (OpponentFieldStates status : OpponentFieldStates.values()) {
			if (status == OpponentFieldStates.Empty) {
				continue;
			}
			sb.append(status.toString());
			sb.append(" - ");
			sb.append(status.name());
			sb.append("; ");
		}
		sb.append("\n");

		return sb.toString();
	}

	@Override
	public String toString() {
		String labelWithNums = generateHorizontalLabel();
		char[] chars = generateVerticalLabels();

		StringBuilder sb = new StringBuilder();
		sb.append("  MY:");
		sb.append("                           ");
		sb.append("OPPONENT:\n");

		sb.append("  ");
		sb.append(labelWithNums);
		sb.append("   |     ");
		sb.append(labelWithNums);
		sb.append("\n");

		char currentLetter;
		for (int i = 0; i < DIMENSION; i++) {

			currentLetter = chars[i];
			sb.append(currentLetter);
			sb.append(" ");
			for (int j = 0; j < DIMENSION; j++) {
				sb.append(myMap[i][j].toString());
				sb.append(" ");
			}

			sb.append("    |   ");

			sb.append(currentLetter);
			sb.append(" ");

			for (int j = 0; j < DIMENSION; j++) {
				sb.append(opponentMap[i][j].toString());
				sb.append(" ");
			}

			sb.append("\n");
		}

		return sb.toString();
	}

	private MyFieldStates[][] initMyMap() {
		MyFieldStates[][] map = new MyFieldStates[DIMENSION][DIMENSION];
		for (int i = 0; i < DIMENSION; i++) {
			for (int j = 0; j < DIMENSION; j++) {
				map[i][j] = MyFieldStates.Empty;
			}
		}
		return map;
	}

	private OpponentFieldStates[][] initOpponentMap() {
		OpponentFieldStates[][] map = new OpponentFieldStates[DIMENSION][DIMENSION];
		for (int i = 0; i < DIMENSION; i++) {
			for (int j = 0; j < DIMENSION; j++) {
				map[i][j] = OpponentFieldStates.Empty;
			}
		}
		return map;
	}

	private char[] generateVerticalLabels() {
		char[] chars = new char[DIMENSION];
		char c = 'A';
		for (int i = 0; i < DIMENSION; i++) {
			chars[i] = c;
			c++;
		}

		return chars;
	}

	private String generateHorizontalLabel() {
		StringBuilder sb = new StringBuilder();
		for (int i = 1; i <= DIMENSION; i++) {
			sb.append(i + " ");
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		GameMap map = new GameMap();
		map.initMyMapWithSampleData();
		map.initOpponentMapWithSampleData();
		System.out.println(map);
		System.out.println(map.getLegend());
	}

}
